﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web.Routing;
using System.Web.Script.Serialization;

namespace Sparrow.VisualStudio.Debugger.RouteVisualizer
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();

            this.RouteCollection = new RouteCollection();
        }

        
        public RouteCollection RouteCollection
        {
            get;
            set;
        }

        public DebugHttpContext RequestContext
        {
            get;
            set;
        }

        private void frmMain_Shown(object sender, EventArgs e)
        {
            MatchRoutes();
            this.txtRelativeUrl.Text = this.RequestContext.Request.AppRelativeCurrentExecutionFilePath;
            this.txtPathInfo.Text = this.RequestContext.Request.PathInfo;
        }

        List<RouteRow> Rows
        {
            get;
            set;
        }

        void MatchRoutes()
        {
            this.Rows = new List<RouteRow>();

            using (this.RouteCollection.GetReadLock())
            {
                var json = new JavaScriptSerializer();
                for (var i = 0; i < this.RouteCollection.Count; i++)
                {
                    var item = this.RouteCollection[i];
                    if (item is Route)
                    {
                        var route = item as Route;
                        var row = new RouteRow();
                        row.RouteData = route.GetRouteData(this.RequestContext);
                        row.Url = route.Url;
                        row.Defaults = string.Join("&", route.Defaults.Select(m => m.Key + "=" +json.Serialize(m.Value)));
                        row.DataTokens = string.Join("&", route.DataTokens.Select(m => m.Key + "=" +json.Serialize(m.Value)));
                        row.Constraints = string.Join("&", route.Constraints.Select(m => m.Key + "=" +json.Serialize( m.Value)));
                        row.RouteHandler = route.RouteHandler == null ? "" : route.RouteHandler.ToString();

                        Rows.Add(row);
                    }
                    else
                    {
                        var row = new RouteRow();
                        row.RouteData = item.GetRouteData(this.RequestContext);
                        row.Url = item.ToString();
                        row.Defaults = "";
                        row.DataTokens = "";
                        row.Constraints = "";
                        row.RouteHandler = "";
                        Rows.Add(row);
                    }
                }
            }
            this.dgvRoutes.DataSource = Rows;

            this.txtRouteCount.Text = Rows.Count.ToString();
            this.txtMatchedRoutesCount.Text = Rows.Where(i => i.Matched).Count().ToString();

            SelectFirstMatched();
        }

        bool IsRender
        {
            get;
            set;
        }
        private void btnMatch_Click(object sender, EventArgs e)
        {

            if (this.txtRelativeUrl.Text.StartsWith("~/") == false)
            {
                this.txtRelativeUrl.Text = "~/" + this.txtRelativeUrl.Text;
            }
            this.RequestContext = new DebugHttpContext(new DebugHttpRequest(this.txtRelativeUrl.Text, this.txtPathInfo.Text));

            this.IsRender = false;
            this.MatchRoutes();
            this.IsRender = true;

            SelectFirstMatched();
        }

        private void SelectFirstMatched()
        {
            var firstMatched = this.Rows.Select((i, index) => new { i.Matched, index }).Where(i => i.Matched).FirstOrDefault();
            if (firstMatched != null)
            {
                dgvRoutes.Rows[firstMatched.index].Selected = true;
                ShowRouteData(this.Rows[firstMatched.index]);
            }
            else
            {
                ShowRouteData(null);
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmAbout about = new frmAbout();
            about.ShowDialog();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }   

        private void dgvRoutes_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            Rectangle rectangle = new Rectangle(e.RowBounds.Location.X,
                e.RowBounds.Location.Y,
                dgvRoutes.RowHeadersWidth - 4,
                e.RowBounds.Height);

            TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(),
                dgvRoutes.RowHeadersDefaultCellStyle.Font,
                rectangle,
                dgvRoutes.RowHeadersDefaultCellStyle.ForeColor,
                TextFormatFlags.VerticalCenter | TextFormatFlags.Right);

       
            if (dgvRoutes.Rows[e.RowIndex].Cells["Matched"].Value.Equals(true))
            {
                dgvRoutes.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightGreen;
                
            }
        }

        private void dgvRoutes_SelectionChanged(object sender, EventArgs e)
        {
            if (this.IsRender)
            {
                if (this.dgvRoutes.SelectedRows.Count > 0)
                {
                    var index = this.dgvRoutes.SelectedRows[0].Index;
                    this.ShowRouteData(this.Rows[index]);
                }else
                {
                    this.ShowRouteData(null);
                }
            }
        }

        void ShowRouteData(RouteRow row)
        {
          
            if (row != null && row.RouteData != null)
            {
                var json = new JavaScriptSerializer();

                this.dgvRouteData.DataSource = row.RouteData.Values.Select(i => new { Key = i.Key, Value = i.Value }).ToList();
                this.dgvDataTokens.DataSource = row.RouteData.DataTokens.Select(i => new { Key = i.Key, Value =json.Serialize(i.Value) }).ToList();
            }
            else
            {
                var empty = new List<object>().Select(i=> new { Key = "",Value=""}).ToList();
                this.dgvRouteData.DataSource = empty;
                this.dgvDataTokens.DataSource = empty;
            }
        }

       

    }
}
